package com.juku2024.juku.analysis.source

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Color
import android.net.http.SslError
import android.os.Build
import android.text.TextUtils
import android.webkit.*
import com.juku2024.juku.analysis.AnalysisVideoTools
import com.juku2024.juku.analysis.BaseHttpParse
import com.juku2024.juku.analysis.OnParseVideoListener
import com.juku2024.juku.base.BaseApplication
import com.juku2024.juku.db.entity.SourceEntity
import com.juku2024.juku.tools.LogC
import com.juku2024.juku.tools.RxUtils
import com.juku2024.juku.tools.SPUtil
import java.lang.ref.WeakReference


class WebParse: BaseHttpParse() {

    private var webViewReference: WeakReference<WebView>? = null

    override fun parseVideo(context: Context, url: String, source: SourceEntity, callback: OnParseVideoListener) {
        super.parseVideo(context, url, source, callback)
        val sourceName = source.sourceName ?: "unknown"
        val targetUrl = source.url + url
        LogC.e("parse -> web解析 准备加载targetUrl=$targetUrl")
        initAndParse(BaseApplication.context, targetUrl, sourceName, callback)
        outOfTimeAndRetry(source, callback)
    }

    /**
     * 支持js
     * 支持http
     */
    @Suppress("DEPRECATION")
    @SuppressLint("SetJavaScriptEnabled")
    private fun initAndParse(
        context: Context,
        targetUrl: String,
        sourceName: String,
        callback: OnParseVideoListener
    ) {
        try {
            var webView = webViewReference?.get()
            if (webView == null) {
                LogC.e("parse -> 创建webView，准备解析...")
                webView = WebView(context)
                webViewReference = WeakReference(webView)
                initWebView(webView, callback, sourceName)
            }
            webView.loadUrl(targetUrl)
            startTime = System.currentTimeMillis()
        } catch (e: Exception) {
            e.printStackTrace()
            LogC.e("parse -> webview解析过程出现异常...")
            callback.onFail(sourceName)
            release()
        }
    }



    private fun outOfTimeAndRetry(source: SourceEntity, callback: OnParseVideoListener) {
        disposable?.dispose()
        disposable = RxUtils.timer(30000) {
            source.retry++
            LogC.e("parse -> web解析超时，进行尝试 ${source.retry}")
            if (source.retry < 2) { // 允许重试一次
                webViewReference?.get()?.reload()
                outOfTimeAndRetry(source, callback)
                return@timer
            }
            LogC.e("parse -> web解析超时，" + source.sourceName + ", " + source.url)
            callback.onFail(source.sourceName)
        }
    }

    private var  handler: SslErrorHandler? = null
    private fun initWebView(
        webView: WebView,
        callback: OnParseVideoListener,
        sourceName: String
    ) {
        webView.webViewClient = object : WebViewClient() {

            override fun onLoadResource(view: WebView?, url: String?) {
                super.onLoadResource(view, url)
                LogC.e("webview -> onLoadResource...$url")
                if (isVideoUrl(url)) {
                    disposable?.dispose()
                    callback.onSuccess(sourceName, url!!)
                    release()
                    analysisParseDuration(sourceName)
                }
            }

            override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                val url = request?.url?.toString()
                if (url == null || TextUtils.isEmpty(url)) {
                    return false
                }
                return if (Build.VERSION.SDK_INT < 26) {
                    view?.loadUrl(url)
                    true
                } else {
                    false
                }
            }

            /*解决ssl证书问题*/
            override fun onReceivedSslError(
                view: WebView?,
                handler: SslErrorHandler?,
                error: SslError?
            ) {
                if (SPUtil.instance.isNotDisplaySSL) {
                    handler?.proceed()
                    return
                }
                this@WebParse.handler = handler
                LogC.e("webview -> onReceivedSslError...")
                AnalysisVideoTools.showSSLDialog(view?.context)
            }
        }
        webView.setBackgroundColor(Color.BLACK)
        //声明WebSettings子类
        val webSettings = webView.settings
        //如果访问的页面中要与Javascript交互，则webview必须设置支持Javascript
        webSettings.javaScriptEnabled = true
        //设置自适应屏幕，两者合用
        webSettings.useWideViewPort = false //将图片调整到适合webview的大小
        webSettings.loadWithOverviewMode = false // 缩放至屏幕的大小
        //缩放操作
        webSettings.setSupportZoom(true) //支持缩放，默认为true。是下面那个的前提。
        webSettings.builtInZoomControls = true //设置内置的缩放控件。若为false，则该WebView不可缩放
        webSettings.displayZoomControls = false //隐藏原生的缩放控件
        //其他细节操作
        webSettings.cacheMode = WebSettings.LOAD_NO_CACHE //关闭webview中缓存
        webSettings.allowFileAccess = false //设置可以访问文件
        webSettings.javaScriptCanOpenWindowsAutomatically = false //支持通过JS打开新窗口
        webSettings.loadsImagesAutomatically = true //支持自动加载图片
        webSettings.domStorageEnabled = true
        webSettings.setSupportMultipleWindows(false)
    }

    override fun release() {
        handler = null
        disposable?.dispose()
        try {
            val webView = webViewReference?.get()
            webView?.stopLoading()
            webView?.clearHistory()
            webView?.clearCache(true)
            webView?.destroy()
            webViewReference?.clear()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun reset(){
        handler = null
        disposable?.dispose()
        val webView = webViewReference?.get()?:return
        webView.stopLoading()
        webView.clearHistory()
        webView.clearCache(true)
    }

    override fun proceed() {
        super.proceed()
        handler?.proceed()
    }

    override fun cancel() {
        super.cancel()
        handler?.cancel()
    }


    fun isVideoUrl(url: String?): Boolean {
        if (url == null) return false
        val isVideo = url.contains(".mp4", false) || url.contains(".m3u8", false)
                || url.contains(".m3u", false) || url.contains(".flv", false)
        val index = url.indexOf("http", 6, true)
        return isVideo && index == -1
    }
}